package com.keta.generator;

import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.DefaultResourceLoader;

import com.keta.generator.util.ConvertHandler;
import com.keta.generator.vo.Column;
import com.keta.generator.vo.Table;

import freemarker.template.TemplateException;


public class SimpleModuleGenerator extends AbstractGenerate {
	
	public static final String JAVA_PATH="/src/main/java/";
	
	public static final String JSP_PATH="/src/main/webapp/WEB-INF/views/";
	
	public static final String FTL_ENTITY_NAME = "java_entity.ftl";
	public static final String FTL_DAO_NAME = "java_dao.ftl";
	public static final String FTL_SERVICE_NAME = "java_service.ftl";
	public static final String FTL_SERVICE_IMPL_NAME = "java_service_impl.ftl";
	public static final String FTL_CONTROLLER_NAME = "java_controller.ftl";
	
	public static final String FTL_JSP_LIST_NAME = "jsp_list.ftl";
	public static final String FTL_JSP_CREATE_NAME = "jsp_create.ftl";
	public static final String FTL_JSP_EDIT_NAME = "jsp_edit.ftl";
	public static final String FTL_JSP_VIEW_NAME = "jsp_view.ftl";
	
	/**
	 * 生成代码基包
	 */
	protected  String packageName;
	
	/**
	 * 模板路径
	 */
	protected  String templatePath;
	
	/**
	 * 表前缀  
	 */
	protected  String tablePrefix;
	
	/**
	 * 模块名，如果为null则生成默认的模块名称
	 */
	protected String moduleName;
	
	/**
	 * 实体名  javaBean,如果为null则根据表名称生成默认的entityName
	 */
	protected String entityName;
	
	/**
	 * 实例名
	 */
	protected String instanceName;
	
	/**
	 * 项目地址，代码生成地址
	 */
	protected String projectPath ;
	
	/**
	 * 模块基访问地址，如果为null则根据表名生成默认的地址
	 */
	protected String requestMapping;
	
	protected Map<String,Object> model ;
	
	
	/**
	 * 生成表对象
	 */
	protected Table table;

	//每个生成器定义一个配置文件
	public SimpleModuleGenerator() throws Exception {
		super();
	}
	
	protected void init() throws IOException{
		
		Properties pops = new Properties();
		pops.load(SimpleModuleGenerator.class.getResourceAsStream("/generator/simple_module_gen.properties"));
		if(StringUtils.isBlank(packageName)){
			packageName= pops.getProperty("package.name");
		}
		templatePath = pops.getProperty("template.path");
		if(StringUtils.isBlank(tablePrefix)){
			tablePrefix = pops.getProperty("table.prefix");
		}
		if(StringUtils.isBlank(projectPath)){
			projectPath = pops.getProperty("project.path");
		}
		
		//将table中的 sql类型字段转为对应的java类型
		convertJavaType();
		
		//如果设置了entityName,则不使用Table中的实体名替换成设置的entityName
		if(StringUtils.isNotBlank(entityName)){
			this.table.setEntityName(entityName);
		}
		
		if(StringUtils.isNotBlank(instanceName)){
			this.table.setInstanceName(instanceName);
		}
		
		if(StringUtils.isBlank(moduleName)){
			moduleName = table.getTableName();
		}
		
		if(StringUtils.isBlank(requestMapping)){
			requestMapping = "/"  +table.getInstanceName();
		}
		
		model = new HashMap<>();
		model.put("packageName", packageName);
		model.put("moduleName", moduleName);
		model.put("requestMapping", requestMapping);
		model.put("table", table);
		
		boolean hasDate = false;
		boolean hasBigDecimal = false; 
		for (Column column : table.getColumns()) {
			if (column.getJavaType().equals("Date")) {
				hasDate = true;
			} else if (column.getJavaType().equals("BigDecimal")) {
				hasBigDecimal = true;
			}
		}
		
		model.put("hasDate", hasDate);
		model.put("hasBigDecimal", hasBigDecimal);
		
	}
	
	protected void convertJavaType(){
		//转换 表名 为实体类名
		if(StringUtils.isBlank(this.entityName)){
			//将表前缀替换为空
			String tableName = this.table.getTableName();
			tableName = tableName.replace(this.tablePrefix, "");
			String javaBean = ConvertHandler.table2EntityName(tableName);
			this.table.setEntityName(javaBean);
			String instace = Character.toLowerCase(javaBean.charAt(0)) + javaBean.substring(1);
			this.table.setInstanceName(instace);
		}
		
		if(StringUtils.isBlank(moduleName)){
			moduleName = this.table.getEntityName();
		}
		
		//转换各个列
		for(Column column : this.table.getColumns()){
			ConvertHandler.columnHandler(column);
		}
	}
	
	

	public void gen(String tableName) { 
		
		try {
			this.table =  getTable(tableName);
			
			init();
			
			genEntity();
			genDAO();
			genService();
			genServiceImpl();
			genController();
			
			genJspList();
			genJspCreate();
			genJspEdit();
			genJspView();
			
			
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateException e) {
			e.printStackTrace();
		}
		
	}

	public void gen(List<String> tableNames) {
		for(String tableName : tableNames){
			gen(tableName);
		}
	}

	public void genController() throws IOException, TemplateException {
		
		String entityName = table.getEntityName() +"Controller.java";
		String packagePath = StringUtils.replace(packageName, ".", separator);
		String codePath =StringUtils.replace(projectPath + JAVA_PATH  +  packagePath +"/controller/" + entityName , "/", separator);
		
		String code  = render(FTL_CONTROLLER_NAME, model);
		writeCodeToFile(code, codePath);
	}

	public void genService() throws IOException, TemplateException {
		
		
		String entityName = table.getEntityName() +"Service.java";
		String packagePath = StringUtils.replace(packageName, ".", separator);
		String codePath =StringUtils.replace(projectPath + JAVA_PATH  +  packagePath +"/service/" + entityName , "/", separator);
		
		String code  = render(FTL_SERVICE_NAME, model);
		writeCodeToFile(code, codePath);
	}

	public void genServiceImpl() throws IOException, TemplateException {
		String entityName = table.getEntityName() +"ServiceImpl.java";
		String packagePath = StringUtils.replace(packageName, ".", separator);
		String codePath =StringUtils.replace(projectPath + JAVA_PATH  +  packagePath +"/service/impl/" + entityName , "/", separator);
		
		String code  = render(FTL_SERVICE_IMPL_NAME, model);
		writeCodeToFile(code, codePath);
	}
	
	public void genDAO() throws IOException, TemplateException {
		String entityName = table.getEntityName() +"DAO.java";
		String packagePath = StringUtils.replace(packageName, ".", separator);
		String codePath =StringUtils.replace(projectPath + JAVA_PATH  +  packagePath +"/dao/" + entityName , "/", separator) ;
		
		String code  = render(FTL_DAO_NAME, model);
		writeCodeToFile(code, codePath);
	}
	
	public void genEntity() throws IOException, TemplateException {
		String entityName = table.getEntityName() +".java";
		String packagePath = StringUtils.replace(packageName, ".", separator);
		String codePath =StringUtils.replace(projectPath + JAVA_PATH  +  packagePath +"/entity/" + entityName , "/", separator); ;
		
		String code  = render(FTL_ENTITY_NAME, model);
		writeCodeToFile(code, codePath);
	}
	
	public void genJspList() throws IOException, TemplateException {
		String codePath =StringUtils.replace(projectPath + JSP_PATH  + table.getInstanceName() + "/list.jsp", "/", separator); ;
		String code  = render(FTL_JSP_LIST_NAME, model);
		writeCodeToFile(code, codePath);
	}
	
	public void genJspCreate() throws IOException, TemplateException {
		String codePath =StringUtils.replace(projectPath + JSP_PATH  + table.getInstanceName() + "/create.jsp", "/", separator); ;
		String code  = render(FTL_JSP_CREATE_NAME, model);
		writeCodeToFile(code, codePath);
	}
	
	public void genJspEdit() throws IOException, TemplateException {
		
		String codePath =StringUtils.replace(projectPath + JSP_PATH  + table.getInstanceName() + "/edit.jsp", "/", separator); ;
		String code  = render(FTL_JSP_EDIT_NAME, model);
		writeCodeToFile(code, codePath);
	}
	
	public void genJspView() throws IOException, TemplateException {
		
		String codePath =StringUtils.replace(projectPath + JSP_PATH  + table.getInstanceName() + "/view.jsp", "/", separator); ;
		String code  = render(FTL_JSP_VIEW_NAME, model);
		writeCodeToFile(code, codePath);
	}
	 

	public String getPackageName() {
		return packageName;
	}

	public void setPackageName(String packageName) {
		this.packageName = packageName;
	}

	public String getTemplatePath() {
		return templatePath;
	}

	public void setTemplatePath(String templatePath) {
		this.templatePath = templatePath;
	}

	public String getTablePrefix() {
		return tablePrefix;
	}

	public void setTablePrefix(String tablePrefix) {
		this.tablePrefix = tablePrefix;
	}

	public String getModuleName() {
		return moduleName;
	}

	public void setModuleName(String moduleName) {
		this.moduleName = moduleName;
	}

	public String getEntityName() {
		return entityName;
	}

	public void setEntityName(String entityName) {
		this.entityName = entityName;
	}

	public String getRequestMapping() {
		return requestMapping;
	}

	public void setRequestMapping(String requestMapping) {
		this.requestMapping = requestMapping;
	}

	public Table getTable() {
		return table;
	}

	public void setTable(Table table) {
		this.table = table;
	}

	public String getProjectPath() {
		return projectPath;
	}

	public void setProjectPath(String projectPath) {
		this.projectPath = projectPath;
	}

	public String getInstanceName() {
		return instanceName;
	}

	public void setInstanceName(String instanceName) {
		this.instanceName = instanceName;
	}
	
	
}
